﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Badger.Xilinx
{
	/// <summary>
	/// This class can be used to create a Xilinx ISE project file.
	/// </summary>
	public class IseProject
	{
		/// <summary>
		/// Internal class representing a library
		/// and its files
		/// </summary>
		public class LibraryFileCollection
		{
			public string LibraryName;
			public string Directory;
			public List<string> Files;

			protected LibraryFileCollection()
			{
			}

			public LibraryFileCollection(string name, string directory, string[] files)
			{
				this.LibraryName = name;
				this.Files = new List<string>(files);
				this.Directory = directory;
			}

			public LibraryFileCollection(string name, string directory, List<string> files)
			{
				this.LibraryName = name;
				this.Files = files;
				this.Directory = directory;
			}
		}

		/// <summary>
		/// Name of the project
		/// </summary>
		private string projectName;
		public string ProjectName
		{
			get { return projectName; }
			set { projectName = value; }
		}

		/// <summary>
		/// Name of the device family (eg. virtex4)
		/// </summary>
		private string deviceFamily;
		public string DeviceFamily
		{
			get { return deviceFamily; }
			set { deviceFamily = value; }
		}

		/// <summary>
		/// Name of the device (eg. xc2vp4)
		/// </summary>
		private string device;
		public string Device
		{
			get { return device; }
			set { device = value; }
		}

		/// <summary>
		/// Name of the device package (eg. fg456)
		/// </summary>
		private string devicePackage;
		public string DevicePackage
		{
			get { return devicePackage; }
			set { devicePackage = value; }
		}

		/// <summary>
		/// Speedlevel of the device
		/// </summary>
		private string deviceSpeed;
		public string DeviceSpeed
		{
			get { return deviceSpeed; }
			set { deviceSpeed = value; }
		}

		private List<string> statusAll = new List<string>();
		public List<string> StatusAll
		{
			get { return statusAll; }
		}

		/// <summary>
		/// List of source files
		/// </summary>
		private List<string> sourceFiles = 
			new List<string>();

		/// <summary>
		/// List of library files
		/// </summary>
		private List<LibraryFileCollection> libraries = 
			new List<LibraryFileCollection>();
		
		public IseProject()
		{
		}

		public void AddSourceFile(string file)
		{
			sourceFiles.Add(file);
		}

		public void AddSourceFiles(List<string> files)
		{
			sourceFiles.AddRange(files);
		}

		public void AddLibraryFiles(LibraryFileCollection library)
		{
			libraries.Add(library);
		}

		public void AddLibraryFiles(string libraryName, string directory, string[] files)
		{
			LibraryFileCollection library =
				new LibraryFileCollection(libraryName, directory, files);

			libraries.Add(library);
		}

		public void AddLibraryFiles(string libraryName, string directory, List<string> files)
		{
			LibraryFileCollection library = 
				new LibraryFileCollection(libraryName, directory, files);

			libraries.Add(library);
		}

		/// <summary>
		/// Write this project to a file on the disk
		/// </summary>
		/// <param name="filename">File to create</param>
		public void WriteToFile(string filename)
		{
			FileStream stream = null;
			StreamWriter writer = null;

			try
			{
				stream = File.Create(filename);
				writer = new StreamWriter(stream);

				// write the file..
				Write(writer);
			}
			finally
			{
				if (writer != null)
					writer.Close();

				if (stream != null)
					stream.Close();
			}
		}

		/// <summary>
		/// Write this project to a stream writer
		/// </summary>
		/// <param name="writer"></param>
		public void Write(StreamWriter writer)
		{
			writer.WriteLine("JDF G"); // magic?
			writer.WriteLine("// Created by Badger VHDL utility");
			writer.WriteLine("PROJECT {0}", projectName);
			writer.WriteLine("DESIGN {0}", projectName);
			writer.WriteLine("DEVFAM {0}", deviceFamily);
			writer.WriteLine("DEVFAMTIME 0");
			writer.WriteLine("DEVICE {0}", device);
			writer.WriteLine("DEVICETIME 0");
			writer.WriteLine("DEVPKG {0}", devicePackage);
			writer.WriteLine("DEVPKGTIME 0");
			writer.WriteLine("DEVSPEED {0}", deviceSpeed);
			writer.WriteLine("DEVSPEEDTIME 0");
			writer.WriteLine("DEVTOPLEVELMODULETYPE HDL");
			writer.WriteLine("DEVTOPLEVELMODULETYPETIME 0");
			writer.WriteLine("DEVSYNTHESISTOOL XST (VHDL/Verilog)");
			writer.WriteLine("SYNTHESISTOOLTIME 0");
			writer.WriteLine("DEVSIMULATOR Modelsim");
			writer.WriteLine("SIMULATORTIME 0");
			writer.WriteLine("DEVGENERATEDSIMULATIONMODEL VHDL");
			writer.WriteLine("GENERATEDSIMULATIONMODELTIME 0");

			foreach (string file in sourceFiles)
				writer.WriteLine("SOURCE {0}", file);

			foreach(LibraryFileCollection library in libraries)
			{
				System.IO.DirectoryInfo directory =
					new DirectoryInfo(library.Directory);

				System.IO.FileInfo[] files = directory.GetFiles();

				writer.WriteLine("SUBLIB {0} VhdlLibrary vhdl", library.LibraryName);

				foreach (string fileName in library.Files)
				{
					bool found = false;
					// find the file
					foreach (FileInfo file in files)
					{					
						if (file.Name == fileName)
						{
							writer.WriteLine("LIBFILE {0}{1} {2} vhdl", library.Directory, file.Name, library.LibraryName);
							found = true;
							break;
						}						
					}

					if(!found)
						throw new FileNotFoundException(fileName);
				}
			}

			

			writer.WriteLine("[STRATEGY-LIST]");
			writer.WriteLine("Normal=True");
		}
	}
}
